using System;
using MathLib;

namespace UraniaLib
{
	/// <summary>
	/// Summary description for UraniaCoord.
	/// </summary>
	public class UraniaCoord
	{
		public UraniaCoord()
		{

		}


		public static UraniaDMS ConvHMSToDMS(UraniaHMS oHMS)
		{
			//Convert hour format into DMS format
			double fHMS;
			double fDMS;
			UraniaDMS oDMS = new UraniaDMS();

			fHMS = oHMS.getDecFormat();
			fDMS = fHMS * 15;
			oDMS.setDec(fDMS);
			return oDMS;

		}

		public static UraniaHMS ConvDMSToHMS(UraniaDMS oDMS)
		{
			//Convert DMS format into hour format
			double fHMS;
			double fDMS;
			UraniaHMS oHMS = new UraniaHMS();

			fDMS = oDMS.getDecFormat();
			fHMS = fDMS / 15;
			oHMS.setDec(fHMS);
			return oHMS;
		}

		public static double ConvRAToHA(double fRA, DateTime dUT, double fLong)
		{
			//Convert Right Ascension to Hour Angle at specified time and longitude
			double fLST;
			double fHA;

			fLST = UraniaTime.ConvTimeToDec(UraniaTime.CalcLSTFromUT(dUT, fLong));

			fHA = fLST - fRA;
			fHA = Trig.PutIn24Hour(fHA);

			return fHA;
		}

		public static double ConvHAToRA(double fHA, DateTime dUT, double fLong)
		{
			//Convert Hour Angle to Right Ascension at specified time and longitude
			double fLST;
			double fRA;
			
			fLST = UraniaTime.ConvTimeToDec(UraniaTime.CalcLSTFromUT(dUT, fLong));

			fRA = fLST - fHA;
			fRA = Trig.PutIn24Hour(fRA);

			return fRA;
		}

		public static void ConvEquToHor(double fLatitude, double fHA, double fDecl, ref double fAlt, ref double fAzim)
		{
			double fSinAlt;
			double fCosAzim;

			fHA = Trig.DegToRad(fHA * 15);
			fDecl = Trig.DegToRad(fDecl);
			fLatitude = Trig.DegToRad(fLatitude);
			fSinAlt = (Math.Sin(fDecl) * Math.Sin(fLatitude)) + (Math.Cos(fDecl) * Math.Cos(fLatitude) * Math.Cos(fHA));
			fAlt = Math.Asin(fSinAlt);
			fCosAzim = ((Math.Sin(fDecl) - (Math.Sin(fLatitude) * Math.Sin(fAlt))) / (Math.Cos(fLatitude) * Math.Cos(fAlt)));
			fAzim = Trig.RadToDeg(Math.Acos(fCosAzim));
			if (Math.Sin(fHA) > 0)
			{
				fAzim = 360 - fAzim;
			}
			fAlt = Trig.RadToDeg(fAlt);
		}

		public static void ConvHorToEqu(double fLatitude, double fAlt, double fAzim, ref double fHA, ref double fDecl)
		{
			double fSinDecl;
			double fCosH;

			fAlt = Trig.DegToRad(fAlt);
			fAzim = Trig.DegToRad(fAzim);
			fLatitude = Trig.DegToRad(fLatitude);
			fSinDecl = (Math.Sin(fAlt) * Math.Sin(fLatitude)) + (Math.Cos(fAlt) * Math.Cos(fLatitude) * Math.Cos(fAzim));
			fDecl = Math.Asin(fSinDecl);
			fCosH = ((Math.Sin(fAlt) - (Math.Sin(fLatitude) * Math.Sin(fDecl))) / (Math.Cos(fLatitude) * Math.Cos(fDecl)));
			fHA = Trig.RadToDeg(Math.Acos(fCosH));
			if (Math.Sin(fAzim) > 0)
			{
				fHA = 360 - fHA;
			}
			
			fDecl = Trig.RadToDeg(fDecl);
			fHA = fHA / 15.0;
		}

		public static void ConvEquToEcl(double fOblique, double fRA, double fDecl, ref double fELong, ref double fELat)
		{
			double fX;
			double fY;
			double fSinELat;

			fDecl = Trig.DegToRad(fDecl);
			fRA = Trig.DegToRad(fRA * 15);
			fOblique = Trig.DegToRad(fOblique);
			fSinELat = (Math.Sin(fDecl) * Math.Cos(fOblique)) - (Math.Cos(fDecl) * Math.Sin(fOblique) * Math.Sin(fRA));
			fELat = Math.Asin(fSinELat);
			fY = (Math.Sin(fRA) * Math.Cos(fOblique)) + (Math.Tan(fDecl) * Math.Sin(fOblique));
			fX = Math.Cos(fRA);
			fELong = Math.Atan(fY / fX);
			fELong = Trig.RadToDeg(fELong);
			fELat = Trig.RadToDeg(fELat);
			fELong = Trig.TanQuadrant(fX, fY, fELong);
		}

		public static void ConvEclToEqu(double fOblique, double fELong, double fELat, ref double fRA, ref double fDecl)
		{
			double fX;
			double fY;
			double fSinDecl;

			fELong = Trig.DegToRad(fELong);
			fELat = Trig.DegToRad(fELat);
			fOblique = Trig.DegToRad(fOblique);
			fSinDecl = (Math.Sin(fELat) * Math.Cos(fOblique)) + (Math.Cos(fELat) * Math.Sin(fOblique) * Math.Sin(fELong));
			fDecl = Math.Asin(fSinDecl);
			fY = (Math.Sin(fELong) * Math.Cos(fOblique)) - (Math.Tan(fELat) * Math.Sin(fOblique));
			fX = Math.Cos(fELong);
			fRA = Math.Atan(fY / fX);
			fRA = Trig.RadToDeg(fRA);
			fDecl = Trig.RadToDeg(fDecl);
			fRA = Trig.TanQuadrant(fX, fY, fRA);
			fRA = fRA / 15.0;
		}

		public static void ConvEquToGal(double fGalNPRA, double fGalNPDecl, double fGalPlaneAscNode, double fRA, double fDecl, ref double fL, ref double fB)
		{
			double fSinB;
			double fX;
			double fY;
			double fRADiff;

			fGalNPRA = fGalNPRA * 15;
			fRA = fRA * 15;

			fGalNPRA = Trig.DegToRad(fGalNPRA);
			fGalNPDecl = Trig.DegToRad(fGalNPDecl);
			fRA = Trig.DegToRad(fRA);
			fDecl = Trig.DegToRad(fDecl);
			fRADiff = fRA - fGalNPRA;
			fSinB = (Math.Cos(fDecl) * Math.Cos(fGalNPDecl) * Math.Cos(fRADiff)) + (Math.Sin(fDecl) * Math.Sin(fGalNPDecl));
			fB = Math.Asin(fSinB);
			fY = (Math.Sin(fDecl)) - (Math.Sin(fB) * Math.Sin(fGalNPDecl));
			fX = (Math.Cos(fDecl) * Math.Sin(fRADiff) * Math.Cos(fGalNPDecl));
			fL = Math.Atan(fY / fX);
			fL = Trig.RadToDeg(fL);
			fB = Trig.RadToDeg(fB);
			fL = Trig.TanQuadrant(fX, fY, fL);
			fL = fL + fGalPlaneAscNode;
			fL = Trig.PutIn360Deg(fL);
		}

		public static void ConvGalToEqu(double fGalNPRA, double fGalNPDecl, double fGalPlaneAscNode, double fL, double fB, ref double fRA, ref double fDecl)
		{
			double fSinDecl;
			double fX;
			double fY;
			double fLDiff;

			fGalNPRA = fGalNPRA * 15;

			fGalPlaneAscNode = Trig.DegToRad(fGalPlaneAscNode);
			fGalNPDecl = Trig.DegToRad(fGalNPDecl);
			fL = Trig.DegToRad(fL);
			fB = Trig.DegToRad(fB);

			fLDiff = fL - fGalPlaneAscNode;
			fSinDecl = (Math.Cos(fB) * Math.Cos(fGalNPDecl) * Math.Sin(fLDiff)) + (Math.Sin(fB) * Math.Sin(fGalNPDecl));
			fDecl = Math.Asin(fSinDecl);
			fY = (Math.Cos(fB) * Math.Cos(fLDiff));
			fX = (Math.Sin(fB) * Math.Cos(fGalNPDecl)) - (Math.Cos(fB) * Math.Sin(fLDiff) * Math.Sin(fGalNPDecl));
			fRA = Math.Atan(fY / fX);
			fRA = Trig.RadToDeg(fRA);
			fDecl = Trig.RadToDeg(fDecl);
			fRA = Trig.TanQuadrant(fX, fY, fRA);
			fRA = fRA + fGalNPRA;
			fRA = Trig.PutIn360Deg(fRA);

			fRA = fRA / 15.0;
		}

		public static string GetCurrentConst(double fOblique, double fRA, double fDecl)
		{

			double fELong = 0;
			double fELat = 0;
			string sConst;

			ConvEquToEcl(fOblique, fRA, fDecl, ref fELong, ref fELat);
            
			if (fELong <  33.18)
			{
				sConst = "Pisces";
			}
			else if (fELong <  51.16)
			{
				sConst = "Aries";
			}
			else if (fELong <  93.44)
			{
				sConst = "Taurus";
			}
			else if (fELong <  119.48)
			{
				sConst = "Gemini";
			}
			else if (fELong <  135.30)
			{
				sConst = "Cancer";
			}			
			else if (fELong <  173.34)
			{
				sConst = "Leo";
			}
			else if (fELong <  224.17)
			{
				sConst = "Virgo";
			}
			else if (fELong <  242.57)
			{
				sConst = "Libra";
			}
			else if (fELong <  271.26)
			{
				sConst = "Scorpius";
			}			
			else if (fELong <  302.49)
			{
				sConst = "Sagittarius";
			}
			else if (fELong <  311.72)
			{
				sConst = "Capricorn";
			}
			else if (fELong <  348.58)
			{
				sConst = "Aquarius";
			}
			else
			{
				sConst = "Pisces";
			}
			return sConst;
		}
	}
}
